/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package com.plian.system.service.pf.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.common.status.CustomCode;
import com.plian.system.config.RedisUtils;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.dto.im.BaseInvestmentExecutionDTO;
import com.plian.system.dto.im.MainProjectSituationDTO;
import com.plian.system.dto.pf.BusinessReplenishDTO;
import com.plian.system.entity.fr.bulletin.BulletinValue;
import com.plian.system.entity.pf.BaseBusinessIndicatorsOld;
import com.plian.system.entity.pf.BusinessIndicatorsOld;
import com.plian.system.entity.pf.BusinessReplenish;
import com.plian.system.mapper.pf.BusinessReplenishMapper;
import com.plian.system.model.CommonCode;
import com.plian.system.model.R;
import com.plian.system.mybatis.base.BaseFlowService;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.service.fr.bulletin.INewBulletinService;
import com.plian.system.service.im.IEffectiveInvestmentService;
import com.plian.system.service.im.IMainProjectSituationService;
import com.plian.system.service.pf.IBaseBusinessIndicatorsOldService;
import com.plian.system.service.pf.IBusinessIndicatorsOldService;
import com.plian.system.service.pf.IBusinessReplenishService;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.sys.orgzation.OrgzationService;
import com.plian.system.service.wf.FormWorkflowService;
import com.plian.system.vo.fr.bulletin.NewBulletinVO;
import com.plian.system.vo.im.InvestmentMonthSummaryVO;
import com.plian.system.vo.im.MainProjectStatisticsVO;
import com.plian.system.vo.pf.BusinessIndicatorsOldVO;
import com.plian.system.vo.pf.BusinessReplenishSummaryVO;
import com.plian.system.vo.pf.BusinessReplenishVO;
import com.plian.system.vo.report.HeaderVO;
import com.plian.system.vo.report.ReportReturnVO;
import com.plian.system.vo.report.ReportVO;
import com.plian.system.wrapper.pf.BusinessIndicatorsOldWrapper;
import com.plian.system.wrapper.pf.BusinessReplenishWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;

import static com.plian.system.constant.sys.FormStatusConstant.UNREVIEWED;

/**
 * 经营业绩考核补充表 服务实现类
 *
 * @author
 * @since 2019-09-27
 */
@Slf4j
@Service
@AllArgsConstructor
public class BusinessReplenishServiceImpl extends BaseServiceImpl<BusinessReplenishMapper, BusinessReplenish> implements IBusinessReplenishService, BaseFlowService {

	private FormWorkflowService formWorkflowService;

	private IFormCodeService formCodeService;

	private IBaseBusinessIndicatorsOldService baseBusinessIndicatorsService;

	private IBusinessIndicatorsOldService businessIndicatorsService;

	private IMainProjectSituationService mainProjectSituationService;

	private IEffectiveInvestmentService effectiveInvestmentService;

	private Environment environment;

	private OrgzationService orgzationService;

	private RedisUtils redisUtils;

	private INewBulletinService newBulletinService;

	private BusinessReplenishWrapper businessReplenishWrapper;

	private BusinessIndicatorsOldWrapper businessIndicatorsWrapper;


	@Override
	public boolean saveOrUpdate(BusinessReplenish businessReplenish) {

		if (!Optional.ofNullable(businessReplenish.getStatus()).isPresent()) {
			businessReplenish.setStatus(FormStatusConstant.UNREVIEWED);
		}
		if (!Optional.ofNullable(businessReplenish.getId()).isPresent()) {
			businessReplenish.setCode(formCodeService.getCode(FormTypeConstant.PF_BUSINESS_REPLENISH_OLD));
			businessReplenish.setFormType(String.valueOf(FormTypeConstant.PF_BUSINESS_REPLENISH_OLD));
		}

		return super.saveOrUpdate(businessReplenish);
	}

	@Override
	@Transactional(rollbackFor=RuntimeException.class)
	public boolean deleteLogic(List<Long> ids) {
		for (Long id : ids) {
			BusinessReplenish businessReplenish = getById(id);
			if (businessReplenish == null) {
				return false;
			} else if (businessReplenish.getStatus() != null &&
					(businessReplenish.getStatus() != FormStatusConstant.STASH && businessReplenish.getStatus() != FormStatusConstant.UNREVIEWED)) {
				return false;
			}
			formWorkflowService.deleteProcessInstance(String.valueOf(id));
		}

		return super.deleteLogic(ids);
	}

	@Override
	public HashMap<String,Object> commit(String id) {
		handleStatus(Long.valueOf(id), FormStatusConstant.FLOW);

		//将需要提交的流程变量返回，用于工作流侧
		return new HashMap<String,Object>();
	}

	@Override
	public Boolean finish(String id) {
		return handleStatus(Long.valueOf(id), FormStatusConstant.FINISH);
	}

	@Override
	public Boolean reject(String id, int formState, String comment) {
		return handleStatus(Long.valueOf(id), formState);
	}

	@Override
	public String checkMonth(BusinessReplenish businessReplenish) {
		LambdaQueryWrapper<BusinessReplenish> queryWrapper = new LambdaQueryWrapper<>();
		if (!Optional.ofNullable(businessReplenish.getFillingMonth()).isPresent()) {
			return "填报时间为空";
		}
		if (!Optional.ofNullable(businessReplenish.getFillingUnitId()).isPresent()){
			return "填报单位为空";
		}
		queryWrapper.eq(BusinessReplenish::getFillingUnitId, businessReplenish.getFillingUnitId());
		queryWrapper.eq(BusinessReplenish::getFillingMonth, businessReplenish.getFillingMonth());
		BusinessReplenish one = getOne(queryWrapper);
		if (!Optional.ofNullable(one).isPresent()){
			return null;
		}
		if (one.getId().equals(businessReplenish.getId())){
			return null;
		}
		return "该月份已填报";
	}


	/**
	 * 统一处理状态机事件方法
	 *
	 * @param id          主键
	 * @param updateStatus  更新状态
	 * @return boolean
	 */
	private Boolean handleStatus(Long id, int updateStatus) {
		try {
			BusinessReplenish businessReplenish = getById(id);
			/**
			 * 设置审批人和审批时间
			 */
			if (updateStatus == FormStatusConstant.FINISH){
				businessReplenish.setApprovedUser(TokenUtil.getTokenUserId());
				Date now = DateUtil.now();
				businessReplenish.setApprovedTime(now);
			}
			businessReplenish.setStatus(updateStatus);
			updateById(businessReplenish);
			return true;
		} catch (Exception e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
			return false;
		}
	}


	@Override
	public List<PageData> findByIds(List<String> formIds) {
		LambdaQueryWrapper<BusinessReplenish> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.in(BusinessReplenish::getId, Func.toLongList(StringUtils.join(formIds, StringPool.COMMA)));
		List<BusinessReplenish> businessReplenishes = list(queryWrapper);
		List<BusinessReplenishVO> businessReplenishVOS= businessReplenishWrapper.entityToVO(businessReplenishes);
		List<PageData> pageDataList = new ArrayList<>();
		try{
			if (CollectionUtil.isNotEmpty(businessReplenishVOS)){
				for (BusinessReplenishVO vo : businessReplenishVOS){
					PageData pd = new PageData();
					pd.put("id", vo.getId());
					pd.put("UNITNAME", vo.getFillingUnitName());
					pd.put("APPLICANTNAME", vo.getCreateUserName());
					pd.put("applicantId", vo.getCreateUser());
					pd.put("applyOrganizationId", vo.getFillingUnitId());
					pd.put("formType", FormTypeConstant.PF_BUSINESS_REPLENISH_OLD);
					pd.put("orgName", vo.getFillingUnitName());
					pageDataList.add(pd);
				}
			}

			return pageDataList;
		} catch (Exception e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
		}
		return pageDataList;
	}

	@Override
	public List<Integer> getFormType() {
		return Arrays.asList(FormTypeConstant.PF_BUSINESS_REPLENISH_OLD);
	}

	@Override
	@Transactional(rollbackFor=RuntimeException.class)
	public boolean submit(BusinessReplenish businessReplenish) {
		boolean result = saveOrUpdate(businessReplenish);
		return result;
	}

	@Override
	public void goBackToStash(String formId) {
		handleStatus(Long.valueOf(formId), UNREVIEWED);
	}

	@Override
	public R<ReportReturnVO> summary(BusinessReplenishDTO businessReplenishDTO) {
		if (StringUtil.isBlank(businessReplenishDTO.getFillingMonth())){
			businessReplenishDTO.setFillingMonth(DateUtil.format(DateUtil.now(), DateUtil.PATTERN_MONTH));
		}

		if (CollectionUtil.isEmpty(businessReplenishDTO.getFillingUnitIds())){
			return new R(CustomCode.builder().message("填报单位为空").code(1999).success(false).build());
		}

		String fillingUnitId = businessReplenishDTO.getFillingUnitIds().get(0);

		String fillingYear = businessReplenishDTO.getFillingMonth().split("-")[0];
		LambdaQueryWrapper<BaseBusinessIndicatorsOld> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(BaseBusinessIndicatorsOld::getFillingYear, fillingYear).eq(BaseBusinessIndicatorsOld::getStatus, FormStatusConstant.FINISH);
		queryWrapper.eq(BaseBusinessIndicatorsOld::getFillingUnitId, fillingUnitId);
		queryWrapper.orderByDesc(BaseBusinessIndicatorsOld::getCreateTime);

		List<BaseBusinessIndicatorsOld> baseBusinessIndicatorsList = baseBusinessIndicatorsService.list(queryWrapper);
		if (CollectionUtil.isEmpty(baseBusinessIndicatorsList)){
			return new R(CustomCode.builder().message("该单位 经营业绩考核表数据未填报").code(1999).success(false).build());
		}
		BaseBusinessIndicatorsOld baseBusinessIndicators = baseBusinessIndicatorsList.get(0);

		List<BusinessIndicatorsOldVO> voList = businessIndicatorsWrapper.entityToVO(businessIndicatorsService.list(new LambdaQueryWrapper<BusinessIndicatorsOld>()
				.eq(BusinessIndicatorsOld::getBaseBusinessIndicatorsId, baseBusinessIndicators.getId())));
		if (CollectionUtil.isEmpty(voList)){
			return new R(CustomCode.builder().message("该单位 经营业绩考核表数据未填报").code(1999).success(false).build());
		}

		LambdaQueryWrapper<BusinessReplenish> replenishWrapper = new LambdaQueryWrapper<>();
		replenishWrapper.eq(BusinessReplenish::getFillingMonth, businessReplenishDTO.getFillingMonth());
		replenishWrapper.eq(BusinessReplenish::getFillingUnitId, fillingUnitId);
		BusinessReplenish businessReplenish = getOne(replenishWrapper);
		if (!Optional.ofNullable(businessReplenish).isPresent()){
			return new R(CustomCode.builder().message("该单位该月份， 经营业绩月度考核数据未填报").code(1999).success(false).build());
		}
		List<BusinessReplenishSummaryVO> results = new ArrayList<>();

		//月净利润合计
		BigDecimal netWorth = new BigDecimal(0);
		//当月所有者权益
		BigDecimal ownerEquity = new BigDecimal(0);

		// 利润总额
		BigDecimal profitTotal = new BigDecimal(0);
		// 营业总收入
		BigDecimal grossOperatingIncome = new BigDecimal(0);
		// 去年营业总收入
		BigDecimal lastGrossOperatingIncome = new BigDecimal(0);
		//成本费用总额
		BigDecimal totalCost = new BigDecimal(0);

		int month = Integer.valueOf(businessReplenishDTO.getFillingMonth().split("-")[1]);
		NewBulletinVO queryParam = new NewBulletinVO();
		queryParam.setOrgId(fillingUnitId);
		queryParam.setYear(fillingYear);
		try {
			for (int i = 1; i <= month; i++){
				log.info("i----------->" + i);
				if (i < 10){
					queryParam.setMonth("0" + i);
				}else {
					queryParam.setMonth("" + i);
				}
				NewBulletinVO newBulletinVO = newBulletinService.getGroupOneByParam(queryParam);

				if (newBulletinVO != null && CollectionUtil.isNotEmpty(newBulletinVO.getBulletinValues())){
					for (BulletinValue value : newBulletinVO.getBulletinValues()){
						if ("GSYMGSSYZDJLR".equals(value.getColumnName())){
							netWorth = BigDecimalUtil.add(netWorth, value.getMonthAmount());
							break;
						}
					}

				}
			}
			if (month < 10){
				queryParam.setMonth("0" + month);
			}else {
				queryParam.setMonth("" + month);
			}
			NewBulletinVO currentBulletin = newBulletinService.getGroupOneByParam(queryParam);
			if (currentBulletin != null && CollectionUtil.isNotEmpty(currentBulletin.getBulletinValues())){
				for (BulletinValue value : currentBulletin.getBulletinValues()){
					if ("LRZE".equals(value.getColumnName())){
						profitTotal = value.getMonthAmount();
					}
					if ("YYZSLR".equals(value.getColumnName())){
						grossOperatingIncome = value.getMonthAmount();
					}
					if ("YYZSLR".equals(value.getColumnName())){
						grossOperatingIncome = value.getLastYearMonthAmount();
					}

					if ("YYCB".equals(value.getColumnName())
							|| "SJJFJ".equals(value.getColumnName())
							||  "XSFY".equals(value.getColumnName())
							|| "GLFY".equals(value.getColumnName())
							|| "YFFY".equals(value.getColumnName())
							|| "CWFY".equals(value.getColumnName())){
						totalCost = BigDecimalUtil.add(totalCost, value.getMonthAmount());
					}

					if ("GSYMGSDSYZQYZE".equals(value.getColumnName())){
						ownerEquity = value.getMonthAmount();
					}

				}
			}

		}catch (Exception e){
			log.error("获取快报数据失败", e);
		}

		BusinessReplenishSummaryVO yearSummary = BusinessReplenishSummaryVO.builder()
				.indicatorsCategoryName("年度考核得分").orScores(new BigDecimal(0)).build();
		for (BusinessIndicatorsOldVO vo : voList){
			BusinessReplenishSummaryVO businessReplenishSummaryVO = BusinessReplenishSummaryVO.builder()
					.indicatorsCategoryId(vo.getIndicatorsCategoryId()).indicatorsCategoryName(vo.getIndicatorsCategoryName())
					.indicatorsWeight(vo.getIndicatorsWeight()).baseline(vo.getBaseline()).target(vo.getTarget())
					.basicTarget(vo.getBasicTarget()).build();

			int basicScore = 100;
			BigDecimal points = new BigDecimal(0);
			BigDecimal componentScores;
			boolean flag = true;

			switch (vo.getIndicatorsCategoryId().toString()){
				// 净利润
				case "088001001":
					if (netWorth.compareTo(new BigDecimal(0)) == 0  || vo.getTarget() == null){
						flag = false;
						break;
					}
					//年 净利润
					BigDecimal	yearNetWorth =  BigDecimalUtil.divide(netWorth, new BigDecimal(month), 10, BigDecimal.ROUND_HALF_UP, 12);
					// 净利润率
					BigDecimal netWorthRate = BigDecimalUtil.divide(yearNetWorth,
							BigDecimalUtil.divide(BigDecimalUtil.add(ownerEquity, businessReplenish.getNetWorth()), new BigDecimal(2), 4, BigDecimal.ROUND_HALF_UP)
							, 2, BigDecimal.ROUND_HALF_UP, 100);
					if (Optional.ofNullable(netWorthRate).isPresent()){
						Integer rateType;
						if (netWorthRate.compareTo(new BigDecimal(10)) == 1){
							rateType = 1;
						}else if (netWorthRate.compareTo(new BigDecimal(10)) < 1 && netWorthRate.compareTo(new BigDecimal(5)) >= 0){
							rateType = 2;
						}else if (netWorthRate.compareTo(new BigDecimal(5)) == -1 && netWorthRate.compareTo(new BigDecimal(0)) >= 1){
							rateType = 3;
						}else{
							rateType = 4;
						}

						if (Optional.ofNullable(yearNetWorth).isPresent()){
							if (yearNetWorth.compareTo(new BigDecimal(0)) == -1){
								basicScore = 80;

							}else if (yearNetWorth.compareTo(new BigDecimal(0)) >= 0
									&& yearNetWorth.compareTo(new BigDecimal(5000)) == -1){
								switch (rateType){
									case 1:
										basicScore = 92;
										break;
									case 2:
										basicScore = 88;
										break;
									case 3:
										basicScore = 84;
										break;
									case 4:
										basicScore = 80;
										break;
									default:
										break;
								}
							}else if (yearNetWorth.compareTo(new BigDecimal(5000)) >= 0
									&& yearNetWorth.compareTo(new BigDecimal(10000)) == -1){
								switch (rateType){
									case 1:
										basicScore = 94;
										break;
									case 2:
										basicScore = 92;
										break;
									case 3:
										basicScore = 88;
										break;
									case 4:
										basicScore = 80;
										break;
									default:
										break;
								}
							}else if (yearNetWorth.compareTo(new BigDecimal(10000)) >= 0
									&& yearNetWorth.compareTo(new BigDecimal(50000)) == -1){
								switch (rateType){
									case 1:
										basicScore = 96;
										break;
									case 2:
										basicScore = 94;
										break;
									case 3:
										basicScore = 92;
										break;
									case 4:
										basicScore = 80;
										break;
									default:
										break;
								}
							}else if (yearNetWorth.compareTo(new BigDecimal(50000)) >= 0){
								switch (rateType){
									case 1:
										basicScore = 100;
										break;
									case 2:
										basicScore = 96;
										break;
									case 3:
										basicScore = 94;
										break;
									case 4:
										basicScore = 80;
										break;
									default:
										break;
								}
							}
						}
						points = changeCompleteValueByBasicTarget(netWorthRate, businessReplenishSummaryVO.getBasicTarget(),
								businessReplenishSummaryVO.getTarget(), businessReplenishSummaryVO.getBaseline());
					}
					businessReplenishSummaryVO.setCompleteValue(netWorthRate);
					break;
				//市场化运作资产净利润（部分企业）
				case "088001002":
					flag = false;
					break;
				//人工成本利润率（%）
				case "088001003":
					if (profitTotal == null || profitTotal.compareTo(new BigDecimal(0)) == 0 || vo.getTarget() == null){
						flag = false;
						break;
					}
					BigDecimal laborCostRate = BigDecimalUtil.divide(profitTotal, businessReplenish.getTotalLaborCost(), 2, BigDecimal.ROUND_HALF_UP, 100);

					if (Optional.ofNullable(laborCostRate).isPresent()){
						if (laborCostRate.compareTo(vo.getTarget()) == 1){
							points = BigDecimalUtil.multiply(BigDecimalUtil.subtract(laborCostRate, vo.getTarget()), new BigDecimal(0.5));
						}else if (laborCostRate.compareTo(vo.getTarget()) <= 0
								&& laborCostRate.compareTo(vo.getBaseline()) == 1){
							points = BigDecimalUtil.multiply(BigDecimalUtil.subtract(laborCostRate, vo.getBaseline()), new BigDecimal(0.25));
						}else if (laborCostRate.compareTo(vo.getBaseline()) == -1){
							points = BigDecimalUtil.multiply(BigDecimalUtil.subtract(laborCostRate, vo.getBaseline()), new BigDecimal(0.5));
						}
					}
					businessReplenishSummaryVO.setCompleteValue(laborCostRate);
					break;
				// 投资完成率（%）
				case "088002001":
					BaseInvestmentExecutionDTO baseInvestmentExecutionDTO = new BaseInvestmentExecutionDTO();
					baseInvestmentExecutionDTO.setFillingUnitIds(businessReplenishDTO.getFillingUnitIds());
					baseInvestmentExecutionDTO.setFilingMonth(businessReplenishDTO.getFillingMonth());
					List<InvestmentMonthSummaryVO> investmentMonthSummaryVOS = effectiveInvestmentService.summary(baseInvestmentExecutionDTO);
					if (CollectionUtil.isEmpty(investmentMonthSummaryVOS)){
						flag = false;
						break;
					}
					InvestmentMonthSummaryVO investmentMonthSummaryVO = investmentMonthSummaryVOS.get(investmentMonthSummaryVOS.size() - 1);
					businessReplenishSummaryVO.setCompleteValue(investmentMonthSummaryVO.getCompleteProportion());
					if (investmentMonthSummaryVO.getPlanInvestmentTotal().compareTo(new BigDecimal(500000)) > 0){
						basicScore = 110;
					}
					points = BigDecimalUtil.divide(BigDecimalUtil.subtract(investmentMonthSummaryVO.getCompleteProportion(),
							new BigDecimal(basicScore)), new BigDecimal(2), 2, BigDecimal.ROUND_HALF_UP);
					break;
				// 重大项目建设完成率（%）
				case "088002002":
					MainProjectSituationDTO mainProjectSituationDTO = new MainProjectSituationDTO();
					mainProjectSituationDTO.setFillingUnitIds(businessReplenishDTO.getFillingUnitIds());
					mainProjectSituationDTO.setFilingMonth(businessReplenishDTO.getFillingMonth());
					ReportReturnVO reportReturnVO = mainProjectSituationService.statisticsByUnit(mainProjectSituationDTO);
					List<MainProjectStatisticsVO> mainProjectStatisticsVOS = reportReturnVO.getGrids().getData();
					if (CollectionUtil.isEmpty(mainProjectStatisticsVOS)){
						flag = false;
						break;
					}
					MainProjectStatisticsVO mainProjectStatisticsVO = mainProjectStatisticsVOS.get(mainProjectStatisticsVOS.size() - 1);
					if (mainProjectStatisticsVO.getCompletionRate() == null){
						flag = false;
						break;
					}
					businessReplenishSummaryVO.setCompleteValue(mainProjectStatisticsVO.getCompletionRate());
					if (Optional.ofNullable(mainProjectStatisticsVO.getPlanTotalInvestment()).isPresent() &&
							mainProjectStatisticsVO.getPlanTotalInvestment().compareTo(new BigDecimal(500000)) > 0){
						basicScore = 110;
					}
					points = BigDecimalUtil.divide(BigDecimalUtil.subtract(mainProjectStatisticsVO.getCompletionRate(),
							new BigDecimal(basicScore)), new BigDecimal(2), 2, BigDecimal.ROUND_HALF_UP);
					break;
				// 融资成本率（%）
				case "088002003":
					//todo  待处理
					flag = false;
					break;
				//营业收入完成率（%）
				case "088002004":
					if (grossOperatingIncome.compareTo(new BigDecimal(0)) == 0){
						flag = false;
						break;
					}
					BigDecimal grossOperatingIncomeRate = BigDecimalUtil.divide(grossOperatingIncome, businessReplenish.getPlanAnnualRevenue(), 2, BigDecimal.ROUND_HALF_UP, 100);
					BigDecimal increaseRate = BigDecimalUtil.divide(BigDecimalUtil.subtract(grossOperatingIncome, lastGrossOperatingIncome),
							lastGrossOperatingIncome, 2, BigDecimal.ROUND_HALF_UP, 100);
					if (Optional.ofNullable(increaseRate).isPresent() && increaseRate.compareTo(new BigDecimal(50)) == 1){
						basicScore = 110;
					}

					BigDecimal basicRate = new BigDecimal(100);
					if (Optional.ofNullable(grossOperatingIncomeRate).isPresent()){
						if (grossOperatingIncomeRate.compareTo(basicRate) == 1){
							points = BigDecimalUtil.multiply(BigDecimalUtil.subtract(grossOperatingIncomeRate, basicRate), new BigDecimal(0.5));
						}else if (grossOperatingIncomeRate.compareTo(basicRate) == -1){
							points = BigDecimalUtil.subtract(grossOperatingIncomeRate, basicRate);
						}
					}
					businessReplenishSummaryVO.setCompleteValue(grossOperatingIncomeRate);
					break;
				// 成本费用占营业收入比重（%）
				case "088002005":
					if (totalCost.compareTo(new BigDecimal(0)) == 0 || vo.getTarget() == null){
						flag = false;
						break;
					}
					BigDecimal totalCostRate = BigDecimalUtil.divide(totalCost, grossOperatingIncome, 2, BigDecimal.ROUND_HALF_UP, 100);
					if (Optional.ofNullable(totalCostRate).isPresent()) {
						if (totalCostRate.compareTo(vo.getTarget()) == 1) {
							points = BigDecimalUtil.subtract(totalCostRate, vo.getTarget());
						} else if (totalCostRate.compareTo(vo.getTarget()) <= 0
								&& totalCostRate.compareTo(vo.getBaseline()) == 1) {
							points = BigDecimalUtil.divide(BigDecimalUtil.subtract(totalCostRate, vo.getTarget()), new BigDecimal(1.5), 2, BigDecimal.ROUND_HALF_UP);
						} else if (totalCostRate.compareTo(vo.getBaseline()) == -1) {
							points = BigDecimalUtil.subtract(totalCostRate, vo.getBaseline());
						}
					}
					businessReplenishSummaryVO.setCompleteValue(totalCostRate);
					break;
				// 特定工作任务
				case "088002006":
					flag = false;
					break;
				default:
					break;
			}

			if (flag){
				componentScores = BigDecimalUtil.add(points, new BigDecimal(basicScore));
				if (Optional.ofNullable(componentScores).isPresent() &&
						componentScores.compareTo(new BigDecimal(120)) == 1){
					componentScores = new BigDecimal(120);
				}
				businessReplenishSummaryVO.setComponentScores(componentScores);
				businessReplenishSummaryVO.setOrScores(BigDecimalUtil.multiply(componentScores,
						BigDecimalUtil.multiply(businessReplenishSummaryVO.getIndicatorsWeight(),new BigDecimal(0.01))));
				if (Optional.ofNullable(businessReplenishSummaryVO.getOrScores()).isPresent()){
					businessReplenishSummaryVO.getOrScores().setScale(4, BigDecimal.ROUND_HALF_UP);
				}
			}
			yearSummary.setIndicatorsWeight(BigDecimalUtil.add(yearSummary.getIndicatorsWeight(), businessReplenishSummaryVO.getIndicatorsWeight()));
			yearSummary.setOrScores(BigDecimalUtil.add(yearSummary.getOrScores(), businessReplenishSummaryVO.getOrScores()));
			results.add(businessReplenishSummaryVO);
		}
//		BusinessReplenishSummaryVO partySummary = BusinessReplenishSummaryVO.builder()
//				.indicatorsCategoryName("党建综合指标").indicatorsWeight(baseBusinessIndicators.getPartyIndicatorsWeight())
//				.componentScores(businessReplenish.getPartyScore())
//				.orScores(BigDecimalUtil.multiply(businessReplenish.getPartyScore(),
//						BigDecimalUtil.multiply(baseBusinessIndicators.getPartyIndicatorsWeight(),new BigDecimal(0.01)))).build();
//		BusinessReplenishSummaryVO specialSummary = BusinessReplenishSummaryVO.builder()
//				.indicatorsCategoryName("特别项目加分").componentScores(businessReplenish.getSpecialProjectsScore())
//				.orScores(businessReplenish.getSpecialProjectsScore()).build();

		BusinessReplenishSummaryVO hedgeSummary = BusinessReplenishSummaryVO.builder()
				.indicatorsCategoryName("保值增值率").componentScores(businessReplenish.getHedgeRadio()).build();

//		yearSummary.setIndicatorsWeight(BigDecimalUtil.add(yearSummary.getIndicatorsWeight(), partySummary.getIndicatorsWeight()));
//		yearSummary.setOrScores(BigDecimalUtil.add(yearSummary.getOrScores(), partySummary.getOrScores()));
		yearSummary.setOrScores(BigDecimalUtil.add(yearSummary.getOrScores(), hedgeSummary.getOrScores()));
		results.add(yearSummary);
		results.add(hedgeSummary);


		ReportVO reportVO = new ReportVO();

		reportVO
				.addHeader(HeaderVO.builder().key("indicatorsCategoryName").title("指标名称").build())
				.addHeader(HeaderVO.builder().key("indicatorsWeight").title("指标权重").build())
				.addHeader(HeaderVO.builder().key("baseline").title("基准值").build())
				.addHeader(HeaderVO.builder().key("target").title("(对标)目标值").build())
				.addHeader(HeaderVO.builder().key("basicTarget").title("基本目标值").build())
				.addHeader(HeaderVO.builder().key("completeValue").title("完成值").build())
				.addHeader(HeaderVO.builder().key("componentScores").title("分项得分").build())
				.addHeader(HeaderVO.builder().key("orScores").title("折合得分").build());

		reportVO.setData(results);
		ReportReturnVO reportReturnVO = new ReportReturnVO();
		reportReturnVO.setGrids(reportVO);
		R<ReportReturnVO> obj =  new R<>(CommonCode.SUCCESS);
		obj.setPageData(reportReturnVO);
		return obj;
	}

	@Override
	public R summaryExport(BusinessReplenishDTO businessReplenishDTO){
		R<ReportReturnVO> r = summary(businessReplenishDTO);
		if (!r.isSuccess()){
			return r;
		}
		String fillingUnitId = businessReplenishDTO.getFillingUnitIds().get(0);
		PageData org=orgzationService.getCompanyNameById(fillingUnitId);
		String fillingUnitName = org.getString("name");
		List<BusinessReplenishSummaryVO> results = r.getPageData().getGrids().getData();

		Map<String, Object> map = new HashMap<>();
		map.put("fillingUnitName", fillingUnitName);
		map.putAll(exportListToMap(results));

		String key = System.currentTimeMillis() + "-" + UUID.randomUUID().toString().replace("-", "");
		String fileName = key + ".xlsx";
		String exportPath = environment.getProperty("excel.path");

		/**
		 * 导出路径不存在则创建
		 */
		File file = new File(exportPath);
		if (!file.exists()) {
			file.mkdirs();
		}
		InputStream inputStream = this.getClass().getResourceAsStream("/exceldemo/replenishSummaryExport.xlsx");
		ExcelWriter excelWriter = EasyExcel.write(exportPath + fileName).withTemplate(inputStream).build();
		WriteSheet baseWriteSheet = EasyExcel.writerSheet(0).build();
		excelWriter.fill(map, baseWriteSheet);
		excelWriter.finish();

		redisUtils.set(key, fillingUnitName + "公司_" + businessReplenishDTO.getFillingMonth() + "_经营业绩考核表", 10 * 60);
		PageData pageData = new PageData();
		pageData.put("key",  key);
		R objResult = new R(CommonCode.SUCCESS);
		objResult.setPageData(pageData);
		return objResult;
	}

	private HashMap<String, Object> exportListToMap(List<BusinessReplenishSummaryVO> results){
		HashMap<String, Object> map = new HashMap<>(128);
		if (CollectionUtil.isNotEmpty(results)){
			for (int i = 0; i < results.size(); i++){
				BusinessReplenishSummaryVO result = results.get(i);
				map.put("indicatorsCategoryName" + i, result.getIndicatorsCategoryName());
				map.put("indicatorsWeight" + i, BigDecimalUtil.toString(result.getIndicatorsWeight()));
				map.put("baseline" + i, BigDecimalUtil.toString(result.getBaseline()));
				map.put("basicTarget" + i, BigDecimalUtil.toString(result.getBasicTarget()));
				map.put("target" + i, BigDecimalUtil.toString(result.getTarget()));
				map.put("completeValue" + i, BigDecimalUtil.toString(result.getCompleteValue()));
				map.put("componentScores" + i, BigDecimalUtil.toString(result.getComponentScores(), false));
				map.put("orScores" + i, BigDecimalUtil.toString(result.getOrScores(), false));
			}
		}
		return map;
	}

	/**
	 * 加减分
	 * @param completeValue
	 * @param basicTarget
	 * @param target
	 * @param baseline
	 * @return
	 */
	private BigDecimal changeCompleteValueByBasicTarget(BigDecimal completeValue, BigDecimal basicTarget, BigDecimal target, BigDecimal baseline){
		if (!Optional.ofNullable(completeValue).isPresent() || !Optional.ofNullable(basicTarget).isPresent()
				|| !Optional.ofNullable(baseline).isPresent()){
			return new BigDecimal(0);
		}
		// 完成值 优于等于对标目标值
		if (completeValue.compareTo(target) >= 0){
			return BigDecimalUtil.multiply(BigDecimalUtil.subtract(completeValue, baseline), new BigDecimal(40));
		}

		// 完成值优于等于基本目标值差于对标目标值
		if (completeValue.compareTo(target) == -1 && completeValue.compareTo(basicTarget) >= 0){
			return BigDecimalUtil.multiply(BigDecimalUtil.subtract(completeValue, baseline), new BigDecimal(24));
		}

		// 完成值差于基本目标值并优于等于基准值
		if (completeValue.compareTo(basicTarget) == -1 && completeValue.compareTo(baseline) >= 0){
			return BigDecimalUtil.multiply(BigDecimalUtil.subtract(completeValue, baseline), new BigDecimal(20));
		}

		// 完成值差于基准值
		if (completeValue.compareTo(baseline) == -1){
			return BigDecimalUtil.multiply(BigDecimalUtil.subtract(completeValue, baseline), new BigDecimal(20));
		}

		return new BigDecimal(0);
	}

}
